/**
 * 通过经纬度字符串得到地理位置
 * 纬度在前，经度在后
 */
const getGeoPoint = (position, db) => {
	if (position) {
		var lng, lat
		if (typeof(position) === 'string') {
			const arr = position.split(',')
			lng = parseFloat(nospaceStr(arr[1]))
			lat = parseFloat(nospaceStr(arr[0]))
		} else if (Array.isArray(position) && position.length === 2) {
			lng = position[0]
			lat = position[1]
		}
		if (-180 > lng && 180 < lng && -90 > lat && 90 < lat) {
			// 不满足经纬度要求
		} else {
			return new db.Geo.Point(lng, lat)
		}
	}
	return null
}

/**
 * 处理更新的特殊类型数据
 * JQL语法暂不支持使用更新操作符
 * 前端无法使用，恐怕只有后端非jql语法才能调用
 * 
 * db：当前云服务空间对象的数据库对象
 * data：当前数据对象
 * key：当前字段名
 * 当前字段名对应的值。如果是需要处理的，其内部结构如下 ：
 * 	update：传入的内容
 * 	updateType：特殊的类型
 * 		current：保证是服务器当前的时间。不需要update
 * 		set：能保证把key这个字段修改为update这个对象，否则只是修改update里面所涉及的属性
 * 		remove：删除该字段。不需要update
 * 		inc：原子自增。多个用户同时写，对数据库来说都是将字段自增，不会有后来者覆写前者的情况。update不传，默认自增1；
 * 		mul：原子自增。多个用户同时写，对数据库来说都是将字段自乘，不会有后来者覆写前者的情况。update不传，默认自乘2；
 * 		min：给定一个值，只有该值小于字段当前值才进行更新
 * 		max：给定一个值，只有该值大于字段当前值才进行更新
 * 		rename：字段重命名。如果需要对嵌套深层的字段做重命名，需要用点路径表示法。不能对嵌套在数组里的对象的字段进行重命名
 * 
 * 		remove：表示删除该字段。可能不能实现
 * 		push：表示向数组尾部增加元素。如果要增加多个元素类似于concat。可能不能实现
 * 		pop：表示删除数组尾部元素。可能不能实现
 * 		unshift：表示向数组头部增加元素。如果要增加多个元素类似于concat。可能不能实现
 * 		shift：表示删除数组头部元素。可能不能实现
 * 
 * 		GeoPoint：地理位置。update是以,隔开的经纬度。纬度在前，经度在后
 * 		GeoLineStringLine：地理路径。update是GeoPoint字符串数组
 * 		GeoPolygon：地理多边形。update是GeoLineStringLine数组数组
 * 		GeoMultiPoint：多个地理位置点。update是GeoPoint字符串数组
 * 		GeoMultiLineString：多个地理路径。update是GeoLineStringLine数组数组
 * 		GeoMultiPolygon：多个地理多边形。update是GeoPolygon数组数组数组
 */
module.exports = (key, data = {}, db = uniCloud.database()) => {
	const dbCmd = db.command
	var {updateType, update, type, coordinates} = data[key] || {}
	if (type === 'Point' && coordinates.length === 2) {
		data[key] = getGeoPoint(coordinates, db)
	} else {
		switch (updateType){
			case 'current': // 保证是服务器当前的时间
				data[key] = data.alert_time || Date.now()
				break
			case 'set': // 能保证把key这个字段修改为update这个对象，否则只是修改update里面所涉及的属性
				data[key] = dbCmd.set(update)
				break
			case 'remove': // 删除该字段。如果删除数组中的元素，形如key.index或key[index]，会保留一个null，没有更好的实现前，应查询一遍数据，再整个替换掉
				data[key] = dbCmd.remove()
				break
			case 'inc': // 原子自增。多个用户同时写，对数据库来说都是将字段自增，不会有后来者覆写前者的情况。默认自增1
			{
				if (update || update === 0) {
					update = parseFloat(update)
				} else {
					update = 1
				}
				data[key] = dbCmd.inc(update)
			}
				break
			case 'mul': // 多个用户同时写，对数据库来说都是将字段自乘，不会有后来者覆写前者的情况。默认自乘2
			{
				if (update && update === 0) {
					update = parseFloat(update)
				} else {
					update = 2
				}
				data[key] = dbCmd.mul(update === 0 ? 0 : (update || 2))
			}
				break
			case 'min': // 给定一个值，只有该值小于字段当前值才进行更新
				data[key] = dbCmd.min(parseFloat(update))
				break
			case 'max': // 给定一个值，只有该值大于字段当前值才进行更新
				data[key] = dbCmd.max(parseFloat(update))
				break
			case 'rename': // 字段重命名。如果需要对嵌套深层的字段做重命名，需要用点路径表示法。不能对嵌套在数组里的对象的字段进行重命名
				data[key] = dbCmd.rename(update)
				// 对嵌套深层的字段做重命名。key应该a.b的写法。比如：
				// someObject: {
				//     someField: dbCmd.rename('someObject.renamedField')
				// } 等价于:
				// 'someObject.someField': dbCmd.rename('someObject.renamedField')
				break
			case 'push': // 表示向数组尾部增加元素。如果要增加多个元素类似于concat。update恐怕要求是数组
				data[key] = dbCmd.push(update)
				break
			case 'pop': // 表示删除数组尾部元素
				data[key] = dbCmd.pop()
				break
			case 'unshift': // 表示向数组头部增加元素。如果要增加多个元素类似于concat。update恐怕要求是数组
				data[key] = dbCmd.unshift(update)
				break
			case 'shift': // 表示删除数组头部元素
				data[key] = dbCmd.shift()
				break
			case 'GeoPoint': // 地理位置
				data[key] = getGeoPoint(update, db)
				break
			case 'GeoLineStringLine': // 地理路径
			{
				if (update && Array.isArray(update) && update.length > 0) {
					const array = []
					update.map(item => {
						array.push(getGeoPoint(item, db))
					})
					data[key] = new db.Geo.LineString(array)
				}
			}
				break
			case 'GeoPolygon': // 地理多边形
			{
				if (update && Array.isArray(update) && update.length > 0) {
					const array = []
					update.map(record => {
						const arr1 = [] // 路径
						record.map(item => {
							arr1.push(getGeoPoint(item, db))
						})
						// 多个点组成路径
						array.push(new db.Geo.LineString(arr1))
					})
					// 多个路径组成多边形
					data[key] = new db.Geo.Polygon(array)
				}
			}
				break
			case 'GeoMultiPoint': // 多个地理位置点
			{
				if (update && Array.isArray(update) && update.length > 0) {
					const array = []
					update.map(item => {
						array.push(getGeoPoint(item, db))
					})
					data[key] = new db.Geo.MultiPoint(array)
				}
			}
				break
			case 'GeoMultiLineString': // 多个地理路径
			{
				if (update && Array.isArray(update) && update.length > 0) {
					const array = []
					update.map(record => {
						const arr1 = [] // 路径
						record.map(item => {
							arr1.push(getGeoPoint(item, db))
						})
						// 多个点组成路径
						array.push(new db.Geo.LineString(arr1))
					})
					// 多个路径组成多边形
					data[key] = new db.Geo.MultiLineString(array)
				}
			}
				break
			case 'GeoMultiPolygon': // 多个地理多边形
			{
				if (update && Array.isArray(update) && update.length > 0) {
					const array = []
					update.map(polygon => {
						const arr1 = [] // 多边形
						polygon.map(record => {
							const arr2 = [] // 路径
							record.map(item => {
								arr2.push(getGeoPoint(item, db))
							})
							// 多个点组成路径
							arr1.push(new db.Geo.LineString(arr2))
						})
						// 多个路劲组成多边形
						array.push(new db.Geo.Polygon(arr1))
					})
					// 多个路径组成多边形
					data[key] = new db.Geo.MultiPolygon(array)
				}
			}
				break
			default:
				break
		}
	}
}